一、初始化 Openshift Django 应用

首先去 Openshift 上创建一个 Django 应用, 关于怎么创建 Openshift 应用参考我另一篇笔记

我这里创建了一个 todolist-smallcpp.rhcloud.com, 然后, 利用另一篇笔记的知识用 SecureCRT 连上我们的服务器.

补充一下用 putty.exe 连接的方法.

首先, 和另一篇笔记中一样, 通过 Git 简明手册 拿到了两个密钥文件: id_rsa(私钥) 和 id_rsa.pub(公钥), 将 id_rsa.pub(公钥) 部署到刚创建的 Django 应用上.

putty.exe 不能识别直接从服务器拷贝来的私钥, 需要使用 puttygen.exe 进行格式转换.

最后, 打开 putty.exe

成功连接后出现下面这样的提示:

login as: your login user name
Authenticating with public key "imported-openssh-key"
...
[todolist-smallcpp.rhcloud.com your login user name]\>


二、配置默认的 Django

用 Openshift 创建的 Django 应用默认有一个 Hello World (你懂的...), 但此时我们直接访问 https://todolist-smallcpp.rhcloud.com 是会报错的...需要配置下.

我们先用 git 把 Openshift 上的 Django 项目 pull 回本地 (git 地址在创建应用时网站上会提示), 该项目目录如下:

里面有个 Readme.md, 阅读后发现下面这些信息:

三、安装 todolist 项目

todolist 我弄了个开源的源码, clone 到本地, 将目录更名为 todolist 并放到步骤二 pull 回本地的 Django 项目根目录的 wsgi 目录下, 并删除自带的 myproject 目录 (注意, 备份下 myproject 里的 settings.py, 后面有用).

然后有几个关键地方要配置:

首先是 setup.py 文件, 其中有一项 install_requires 很重要, 它表示项目中用到的第三方 python 库, 填在里面的项 push 到 openshift 后, openshift 会自动调用 easy_install 进行安装, 例如:

install_requires = ['Django<=1.8', 'django-markdown', 'django-markdown-deux==1.0.5', 'markdown2==2.3.0', 'markdown']



然后打开 \todolist\.openshift\action_hooks 目录下的 deploy 文件, 这里面保存的是当 push 到 openshift 后执行的动作, 我们把里面的 myproject 改为 todolist.

#!/bin/bash
# This deploy hook gets executed after dependencies are resolved and the
# build hook has been run but before the application has been started back
# up again.  This script gets executed directly, so it could be python, php,
# ruby, etc.

if [ ! -f "$OPENSHIFT_DATA_DIR"secrets.json ]; then
    echo "Generating $OPENSHIFT_DATA_DIR/secrets.json"
    python "$OPENSHIFT_REPO_DIR"libs/secrets.py > "$OPENSHIFT_DATA_DIR"secrets.json
fi

# GETTING-STARTED: change 'todolist' to your project name:
echo "Executing 'python $OPENSHIFT_REPO_DIR/wsgi/todolist/manage.py migrate --noinput'"
# GETTING-STARTED: change 'todolist' to your project name:
python "$OPENSHIFT_REPO_DIR"wsgi/todolist/manage.py migrate --noinput

# GETTING-STARTED: change 'todolist' to your project name:
echo "Executing 'python $OPENSHIFT_REPO_DIR/wsgi/todolist/manage.py collectstatic --noinput'"
# GETTING-STARTED: change 'todolist' to your project name:
python "$OPENSHIFT_REPO_DIR"wsgi/todolist/manage.py collectstatic --noinput



再进入 wsgi 文件夹, 里面有个 application 的文件

#!/usr/bin/env python
import os
import sys
## GETTING-STARTED: make sure the next line points to your settings.py:
os.environ['DJANGO_SETTINGS_MODULE'] = 'openshift.settings'
## GETTING-STARTED: make sure the next line points to your django project dir:
sys.path.append(os.path.join(os.environ['OPENSHIFT_REPO_DIR'], 'wsgi', 'openshift'))
virtenv = os.environ['APPDIR'] + '/virtenv/'
## GETTING-STARTED: make sure the next line has the right python version:
os.environ['PYTHON_EGG_CACHE'] = os.path.join(virtenv, 'lib/python2.7/site-packages')
virtualenv = os.path.join(virtenv, 'bin/activate_this.py')
try:
    execfile(virtualenv, dict(__file__=virtualenv))
except:
    pass
import django.core.wsgi
application = django.core.wsgi.get_wsgi_application()



注意这两行:

os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'
sys.path.append(os.path.join(os.environ['OPENSHIFT_REPO_DIR'], 'wsgi', 'myproject'))



改为:

os.environ['DJANGO_SETTINGS_MODULE'] = 'simple_todo.settings'
sys.path.append(os.path.join(os.environ['OPENSHIFT_REPO_DIR'], 'wsgi', 'todolist'))



注意, 别改错了, 第一个是 simple_todo.settings, 别改成 todolist.settings 了.

最后, 进入 \todolist\wsgi\todolist\simple_todo 目录, 用之前从 myproject 里备份的 settings.py 替换掉 simple_todo 里的 settings.py.

但要做下修改, 把 settings.py 里的 myproject 替换成 simple_todo, 然后在 INSTALLED_APPS 里添加一项 todo, 再把 Debug 属性改为 False (如果部署到 openshift 后发现有问题, 可以改为 True 后进行调试, 调试完毕再改为 False), 改完后的 settings.py 如下:

"""
Django settings for simple_todo project.

For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
DJ_PROJECT_DIR = os.path.dirname(__file__)
BASE_DIR = os.path.dirname(DJ_PROJECT_DIR)
WSGI_DIR = os.path.dirname(BASE_DIR)
REPO_DIR = os.path.dirname(WSGI_DIR)
DATA_DIR = os.environ.get('OPENSHIFT_DATA_DIR', BASE_DIR)

import sys
sys.path.append(os.path.join(REPO_DIR, 'libs'))
import secrets
SECRETS = secrets.getter(os.path.join(DATA_DIR, 'secrets.json'))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = SECRETS['secret_key']

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
TEMPLATE_DEBUG = DEBUG

from socket import gethostname
ALLOWED_HOSTS = [
    gethostname(), # For internal OpenShift load balancer security purposes.
    os.environ.get('OPENSHIFT_APP_DNS'), # Dynamically map to the OpenShift gear name.
    #'example.com', # First DNS alias (set up in the app)
    #'www.example.com', # Second DNS alias (set up in the app)
]


# Application definition

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'todo',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

# GETTING-STARTED: change 'simple_todo' to your project name:
ROOT_URLCONF = 'simple_todo.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'simple_todo.wsgi.application'

# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        # GETTING-STARTED: change 'db.sqlite3' to your sqlite3 database:
        'NAME': os.path.join(DATA_DIR, 'db.sqlite3'),
    }
}

# Internationalization
# https://docs.djangoproject.com/en/1.8/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(WSGI_DIR, 'static')



静态文件的处理

比如 CSS、图片等等, 一般 Django 应用的静态文件的目录是在 settings.py 中配置的, 但是 OpenShift 使用了不一样的方式, 所有的静态文件都将被放置在 wsgi/static 目录下.

貌似在 openshift 中, css 文件中的 url 属性不生效, 我现在把 css 中的 url 属性都移到 html 标签中嵌套了...

四、DIY todolist

上面的开源项目基于实现了 todolist 的功能, 不好的是暂时缺少用户管理系统 (所有人访问都是同一个 todolist), 所以准备 DIY 一下, 加一个用户系统.

五、最后

重要的事再说一次:

由于 syncdb 的尿性, 如果修改了数据库结构, 需要先执行 rm -f $OPENSHIFT\_DATA\_DIR/db.sqlite3, 再执行次 python $OPENSHIFT_REPO_DIR/wsgi/myproject/manage.py syncdb.

修改后的项目, 我放在 git@oschina 上了, 可以参考参考...